﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Web;
using System.Web.Hosting;
using System.IO;

namespace EnCor.Hosting.WSHosting
{
    public class HttpListenerWrapper : MarshalByRefObject
    {
        private HttpListener _listener;
        private string _virtualDir;
        private string _physicalDir;
        private IHttpHandlerFactory _HandlerFactory;

        /// <summary>
        /// Configure the HttpListenerWrapper, pass a WebServiceMapCollection if need to start Listener in a seperated domain.
        /// </summary>
        /// <param name="prefixes"></param>
        /// <param name="v"></param>
        /// <param name="p"></param>
        /// <param name="maps"></param>
        public void Configure(string[] prefixes, string v, string p, WebServiceMapCollection maps)
        {
            _virtualDir = v;
            _physicalDir = p;
            _listener = new HttpListener();
            _HandlerFactory = new RequestHandlerFactory(maps);

            foreach (string prefix in prefixes)
                _listener.Prefixes.Add(prefix);
        }

        public void Configure(string[] prefixes, string v, string p, IHttpHandlerFactory factory)
        {
            _virtualDir = v;
            _physicalDir = p;
            _listener = new HttpListener();
            _HandlerFactory = factory;

            foreach (string prefix in prefixes)
                _listener.Prefixes.Add(prefix);
        }

        public void Start()
        {
            _listener.Start();
            //while (true)
            {
                try
                {
                    _listener.BeginGetContext(ProcessRequest, null);
                }
                catch (HttpListenerException ex)
                {
                    Console.Write(ex);
                    // log exception;
                }

            }
            //while (true)
            //{
            //    var ctx = _listener.GetContext();
            //    ctx.Response.OutputStream.Flush();
            //    ctx.Response.Close();
            //}
        }

        public void Stop()
        {
            _listener.Stop();
        }

        private void ProcessRequest(IAsyncResult ar)
        {
            try
            {
                HttpListenerContext ctx = _listener.EndGetContext(ar);
                Console.WriteLine("Get Request: {0}", ctx.Request);

                string page = ctx.Request.Url.LocalPath.Replace("/", "");
                string query = ctx.Request.Url.Query.Replace("?", "");

                //using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream))
                //{
                //    Console.WriteLine("hello");
                //    writer.WriteLine("<html><head><title>The WebServer Test</title></head><body>");
                //    writer.WriteLine("<div style=\"height:20px;color:blue;text-align:center;\"><p> hello</p></div>");
                //    writer.WriteLine("<ul>");

                //    foreach (string header in ctx.Request.Headers.Keys)
                //    {
                //        writer.WriteLine("<li><b>{0}:</b>{1}</li>", header, ctx.Request.Headers[header]);

                //    }
                //    writer.WriteLine("</ul>");
                //    writer.WriteLine("</body></html>");

                //    writer.Close();
                //    ctx.Response.Close();
                //}

                MemoryStream stream = new MemoryStream();
                StreamWriter sw = new StreamWriter(stream);
                HttpListenerWorkerRequest workerRequest =
                    new HttpListenerWorkerRequest(ctx, _virtualDir,
                        _physicalDir);
                HttpContext context = new HttpContext(workerRequest);
                IHttpHandler handler = _HandlerFactory.GetHandler(context, "", workerRequest.GetRawUrl(), "");
                handler.ProcessRequest(context);
                context.Response.End();
                context.Response.OutputStream.Close();
                ctx.Response.OutputStream.Flush();
                ctx.Response.OutputStream.Close();
                



                //HttpListenerWorkerRequest2 workerRequest =
                //    new HttpListenerWorkerRequest2(ctx, _virtualDir,
                //        _physicalDir, sw);
                
                ////HttpRequest request = new HttpRequest(page, ctx.Request.Url.ToString(), query);
                ////HttpResponse response = new HttpResponse(sw);
                ////HttpContext context = new HttpContext(request, response);
                //HttpContext context = new HttpContext(workerRequest);
                ////context.Response.AppendHeader(HttpWorkerRequest.GetKnownRequestHeaderName(HttpWorkerRequest.HeaderContentLength), 
                ////    stream.Length.ToString());

                //IHttpHandler handler = _HandlerFactory.GetHandler(context, "", workerRequest.GetRawUrl(), "");
                //handler.ProcessRequest(context);

                //sw.Flush();
                //ctx.Response.ContentLength64 = stream.Length;

                //workerRequest.FlushResponse(true);
                //context.Response.End();
                //ctx.Response.OutputStream.Write(stream.ToArray(), 0, (int)stream.Length);
                //ctx.Response.OutputStream.Flush();
                //ctx.Response.OutputStream.Close();




                //string page = ctx.Request.Url.LocalPath.Replace("/", "");
                //string query = ctx.Request.Url.Query.Replace("?", "");

                
                //StreamWriter sw = new StreamWriter(stream);

                //SimpleWorkerRequest swr = new SimpleWorkerRequest(page, query, sw);
                //HttpRuntime.ProcessRequest(swr);
                
                //ctx.Response.OutputStream.Write(new byte[] { 1, 2, 3, 5 }, 0, 4);
                //ctx.Response.OutputStream.Write(new byte[] { 1, 2, 3, 5 }, 0, 4);
                ////swr.FlushResponse(false);
                //ctx.Response.OutputStream.Write(new byte[] { 1, 2, 3, 5 }, 0, 4);
                //ctx.Response.ContentLength64 = ctx.Response.OutputStream.Length;
                //swr.FlushResponse(true);

                //ctx.Response.ContentLength64 = stream.Length;
                //byte[] buffer = stream.ToArray();
                //ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
                //ctx.Response.Close();

                _listener.BeginGetContext(ProcessRequest, null);
                //return;

                
                
                
            }
            catch (HttpListenerException ex)
            {
                Console.Write(ex);
                // log exception;
            }



        }
    }
}
